package com.cskaoyan.javase._0abstract._1basic;

/**
 * 抽象类的定义:
 * 在继承体系中，从祖先类开始，随着一个个子类的定义，子类变得越来越具体，而祖先类则更具有一般性和抽象性。在这种情况下，为了体现祖先类在设计上的抽象性，我们只将该类作为派生其他类的父类，而不能创建对象实例。这个时候，这样的类，我们称之为抽象类。
 *
 * 总结:
 * 抽象类还是一个类,但是它是继承层次中作为祖先类而存在的一个类
 *
 * 接下来，我们重点来研究一个抽象类的自身特点和使用。
 * 对于抽象类的语法:
 * [修饰符列表] abstract class 类名{
 *     //类体
 * }
 *
 * 抽象类的特点我们主要从以下角度：
 *      1.类名命名特点
 *          抽象类虽然是类,但它比较特殊
 *          建议在定义抽象类时,用"Abstract"或者"Base"作为抽象类的开头
 *          比如"BasePerson"或者"AbstractStaff"等等
 *
 *     2.能用哪些修饰符？
 *          首先抽象类还是类,访问权限修饰符和普通类是完全一样的
 *          其次它的修饰符列表中是不能有final的
 *          抽象类鼓励继承,和final是冲突的
 *
 *     3.什么时候用抽象类?
 *          抽象类是类,用抽象类一定要考虑继承中的"is-a"关系,不是乱用的
 *          而且抽象类是继承层次中的祖先类 不要随意定义它
 *
 *     4.抽象类的成员特点:
 *
 *          a.普通成员,静态成员的定义,和普通类没有任何区别
 *          b.构造器
 *              抽象类不能自己new对象,这样就断绝了构造器给自身成员赋值的作用
 *              但是自己不能用,还可以给子类使用,
 *              所以抽象类也是需要构造器给自身成员变量赋值的(在new子类对象的过程中)
 *
 *          c.代码块
 *          有构造器就有构造代码块
 *          也可以定义静态代码块
 *
 * 以上回答问题:
 *      1.普通类中能定义的成员和结构,抽象类是不是都可以定义?
 *      都可以
 *
 *      2.抽象类可以不可以没有抽象方法
 *      当然可以
 *
 *      3.判断题: 任何类都有构造器
 *      对的,不管是什么类,必然都有构造器
 *
 *      4.判断题: 对于一个不需要创建对象的类,直接将该类的声明中加abstract关键字,会不会报错?
 *      不会
 *      普通类中有的,抽象类中都有
 *
 * 抽象类中的抽象方法:
 * 抽象类中可以没有抽象方法,但是没有抽象方法的抽象类是没有意义的,正常来说,抽象类就应该有抽象方法
 * 抽象方法的语法:
 * (在成员方法的基础上加abstract去掉方法体)
 * [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 *
 * 抽象方法的作用:
 * 抽象类中的抽象方法,一旦被一个普通类继承
 * 那么就会强制该普通子类实现这个抽象方法(实现方法就是在子类中重写父类方法,符合方法重写的语法)
 * 抽象方法的作用就是一个"占位符"
 * 它给普通子类方法提供了一个约束,子类必须按照约束的条件实现这个方法.
 *
 * 一句话总结抽象类成员特点:
 * 比普通类多一个抽象方法,这就是抽象类
 *
 * 抽象类的继承特点:
 * 抽象类的子类:
 *      1.普通类,必须实现抽象类中所有抽象方法,没得选
 *      2.抽象类,无需强制实现抽象方法了
 *           但是如果想实现 也是可以的
 *           因为抽象类允许实现方法存在
 *
 * 抽象类可以继承抽象类,那么能不能继承一个普通类呢?
 * 当然可以,实际上,抽象类如果没有直接声明继承了某个类,那么它继承Object
 * 抽象类还是类,参与继承时,是要受"单继承"限制,一个类最多继承一个抽象类
 *
 *
 * @since 17:15
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        Student s = new Student(10, 20);
        System.out.println(s.a);
        System.out.println(s.getB());
    }
}

abstract class A {
    int a;

    public A(int a) {
        this.a = a;
    }
}

abstract class BasePerson {
    int a;
    private int b = 10;
    static int c = 20;
    static final int D = 30;

    {
    }

    static {
    }

    public BasePerson(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public BasePerson() {
    }

    public int getB() {
        return b;
    }

    /*
                    抽象类中为什么可以定义带实现的方法?
                    抽象类是抽象的概念,理论上来说,它不应该有实现方法
                    但实际上Java语法支持它
                    当抽象类的所有子类都需要一个方法的实现作为默认实现时,
                    可以把这个实现方法写在抽象类中,那么:
                        子类要么选择直接继承使用
                        要么选择重写再使用
                        总之权力在子类自己手里
                    实际上,抽象类中有实现方法,是很正常的
                 */
    public void test() {
        System.out.println("test");
    }

    public static void testStatic() {
        System.out.println("static");
    }

    // 定义抽象方法
    public abstract void testAbstract();

    public abstract void testAbstract2();

}

// Class 'Student' must either be declared abstract or implement abstract method 'testAbstract()' in 'BasePerson'
class Student extends BasePerson {
    public Student(int a, int b) {
        super(a, b);
    }

    public Student() {
    }

    @Override
    public void testAbstract() {
        System.out.println("我实现了抽象方法!");
    }

    @Override
    public void testAbstract2() {
        System.out.println("xxxx");
    }

}

abstract class BaseTeacher extends BasePerson {
    @Override
    public void testAbstract() {
        System.out.println();
    }
}

abstract class AbstractB {
}